package com.miaoda.miaoda_ai.core;

import com.miaoda.miaoda_ai.ai.AiCodeGeneratorService;
import com.miaoda.miaoda_ai.ai.model.HtmlCodeResult;
import com.miaoda.miaoda_ai.ai.model.MultiFileCodeResult;
import com.miaoda.miaoda_ai.core.parser.CodeParserExecutor;
import com.miaoda.miaoda_ai.core.saver.CodeFileSaverExecutor;
import com.miaoda.miaoda_ai.exception.BusinessException;
import com.miaoda.miaoda_ai.exception.ErrorCode;
import com.miaoda.miaoda_ai.exception.ThrowUtils;
import com.miaoda.miaoda_ai.model.enums.CodeGenTypeEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.io.File;

/**
 * ai生成器门面
 */
@Slf4j
@Service
public class AiGeneratorFacade {

    @Resource
    private AiCodeGeneratorService aiCodeGeneratorService;

    /**
     * 生成代码（生成代码）
     *
     * @param userMessage 用户输入
     * @param codeGenType 生成类型
     * @return 文件
     */

    public File generatorAndSaveCode(String userMessage, CodeGenTypeEnum codeGenType, Long appId) {
        ThrowUtils.throwIf(userMessage == null, ErrorCode.PARAMS_ERROR, "生成类型不能为空");
        switch (codeGenType) {
            case HTML:
                HtmlCodeResult htmlCodeResult = aiCodeGeneratorService.generateHtmlCode(userMessage);
                return CodeFileSaverExecutor.saveCode(htmlCodeResult, codeGenType, appId);
            case MULTI_FILE:
                MultiFileCodeResult multiFileCodeResult = aiCodeGeneratorService.generateMultiFileCode(userMessage);
                return CodeFileSaverExecutor.saveCode(multiFileCodeResult, codeGenType, appId);
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的生成类型");

        }
    }

    /**
     * 流式生成代码（统一入口）
     *
     * @param userMessage 用户输入
     * @param codeGenType 生成类型
     * @return 文件
     */

    public Flux<String> generatorAndSaveCodeStream(String userMessage, CodeGenTypeEnum codeGenType, Long appId) {
        ThrowUtils.throwIf(userMessage == null, ErrorCode.PARAMS_ERROR, "生成类型不能为空");
        return switch (codeGenType) {
            case HTML ->{
                Flux<String> multiFileCodeStream = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
                yield  processCodeStream(multiFileCodeStream,CodeGenTypeEnum.HTML,appId);
            }
            case MULTI_FILE -> {
                Flux<String> htmlCodeStream = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
                yield processCodeStream(htmlCodeStream,CodeGenTypeEnum.MULTI_FILE,appId);
            }
            default -> {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的生成类型");
            }
        };
    }

//    /**
//     * 流式生成代码
//     *
//     * @param userMessage
//     * @return
//     */
//    private Flux<String> generateMultiFileCodeStream(String userMessage) {
//
//        Flux<String> multiFileCodeStream = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
//        return processCodeStream(multiFileCodeStream,CodeGenTypeEnum.MULTI_FILE);
//
//    }
//
//    /**
//     * 流式生成代码
//     *
//     * @param userMessage
//     * @return
//     */
//
//    private Flux<String> generateHtmlCodeStream(String userMessage) {
//        Flux<String> htmlCodeStream = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
//        return processCodeStream(htmlCodeStream,CodeGenTypeEnum.HTML);
//
//    }

    /**
     * 通用流式生成代码
     *
     * @param codeGenType 生成类型
     * @return 流式输出
     */
    private Flux<String> processCodeStream(Flux<String> codeStream, CodeGenTypeEnum codeGenType, Long appId) {
        // 定义一个字符串拼接器，用于拼接多个字符串
        StringBuilder stringBuilder = new StringBuilder();
        return codeStream
                .doOnNext(
                        // 每当接收到一个字符串时，将其追加到字符串拼接器中
                        chunk -> stringBuilder.append(chunk))
                .doOnComplete(() -> {
                    // 当接收完成时，将拼接后的字符串保存为文件
                    try {
                        String completeCode = stringBuilder.toString();
                        Object res = CodeParserExecutor.executeParser(codeGenType, completeCode);
                        File file = CodeFileSaverExecutor.saveCode(res, codeGenType, appId);
                        log.info("保存文件成功：{}", file.getAbsolutePath());
                    } catch (Exception e) {
                        log.error("保存文件失败：{}", e.getMessage());
                    }
                });

    }
}
